feat(generator): docs_kit:page + Registry v2 — one-line page registration - #29
Merged
Merged
Conversation
…tion ## Summary Adds `rails g docs_kit:page "Title" --group=Guide`, which scaffolds a docs page's class AND its registry line in one command — the unit of work for "add a page" drops to one shell command plus writing content. This required Registry v2 (the `page` DSL the generator injects), so both land together (closes #12, #13). ### Registry v2 (#12) - `DocsKit::Registry` gains an opt-in declarative schema: `page(title, group:, slug:, view:, icon:)` with `path_prefix`/`view_namespace`. slug/view derive from the title (parameterize / camelize), both overridable. A default `Entry` gives readers + `href` + `view_class` (safe_constantize under view_namespace, nil until authored). `nav_items` returns `{ group => [NavItem] }` for authored pages only — the transform every site hand-wrote. Mixing `page` and `entries` raises a clear error. - `Configuration#nav_registries` (default `{}`): `nav_groups` derives the whole sidebar from it, dropping empty groups. An explicit `c.nav` lambda still wins (full backwards compatibility). - Requires the ActiveSupport inflections core-ext so the gem derives slugs/views standalone (a host app already has it). ### Page generator (#13) - `lib/generators/docs_kit/page/` writes the page in the compact class form (`class Views::Docs::Pages::X < DocsUI::Page`) — Zeitwerk resolves it through the directory-implied namespaces, killing the 8-line nesting tax. Injects `page "Title", group: "Group"` after the last `page` line so ordering lands at the group's end. `--slug/--view/--eyebrow/--registry` override every derivation. Idempotent (no duplicate line, no file clobber in --skip). A legacy hash-`entries` registry is left untouched with a by-hand instruction printed instead of corrupting it. ### Install path + dogfood + docs - Install templates (`doc.rb.erb`, `docs_kit.rb.erb`, `installation_page.rb.erb`) rewritten to the v2 `page` DSL + `nav_registries` + compact class, so install output matches generator output. - Dogfood `Doc` + initializer converted to v2 (overrides preserve the three slugs/views that don't derive cleanly); sidebar byte-identical before/after. - README: Configure leads with `nav_registries` (custom lambda demoted to advanced); new "Add a page" section leads with the generator. Dogfood authoring page leads with the one-command flow, hand-authoring as "under the hood". ## Test Coverage - spec/docs_kit/registry_spec.rb: page derivation + overrides, all/grouped over page entries, view_class resolution, href, icon, nav_items (authored-only), view_namespace-unset, mixed-mode error. - spec/docs_kit/configuration_spec.rb: nav_registries default/override, nav_groups derivation, empty-group drop, explicit-nav-wins, empty fallback. - spec/generators/page_generator_spec.rb: compact class + constants, v2 injection + ordering, --slug/--view/--eyebrow/--registry, legacy no-mutation, idempotence. - Configuration + Registry at 100% line coverage. ## Verification - [x] bundle exec rake (rspec 153 examples 0 failures + rubocop clean) - [x] Dogfood smoke: `rails g docs_kit:page "Smoke Test" --group=Guide` → page renders at /docs/smoke-test, in sidebar; reverted. - [x] All dogfood pages render 200 with the derived sidebar; URLs preserved.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #12
Closes #13.
Also lands #12 (Registry v2), which #13 depends on — the generator injects the
page "Title", group: "…"line that #12 introduces, so they ship together.Why
Adding a docs page today is quadruple bookkeeping: an 8-line
module Views; module Docs; module Pagesnesting ceremony, a class body, AND a registry line whose four strings must match the class — forget either half and you silently get a missing page. This is the moment a developer decides documentation is too much work.After this PR, adding a page is one command plus writing content:
rails g docs_kit:page "Getting Started" --group=GuideWhat changed
Registry v2 (#12)
DocsKit::Registrygains an opt-inpage(title, group:, slug:, view:, icon:)DSL withpath_prefix/view_namespace. slug/view derive from the title (parameterize/camelize), both overridable per line. A defaultEntrygives readers +href+view_class(safe_constantizeunderview_namespace, nil until authored — no dead links).nav_itemsreturns{ group => [NavItem] }for authored pages only — the transform every site used to hand-write. MixingpageandentriesraisesRegistry::Error.Configuration#nav_registries(default{}):nav_groupsderives the whole sidebar from it (dropping empty groups). An explicitc.navlambda still wins — full backwards compatibility.Page generator (#13)
lib/generators/docs_kit/page/writes the page in the compact class form (class Views::Docs::Pages::X < DocsUI::Page) — Zeitwerk resolves it through the directory-implied namespaces, killing the nesting tax — with a starterDocsUI::Section+ Markdown island.page "Title", group: "Group"after the lastpageline, so ordering lands at the group's end.--slug/--view/--eyebrow/--registryoverride every derivation.--skipmode.entriesregistry is left untouched — the generator writes the page but prints the entry to add by hand rather than corrupting the array.Install path + dogfood + docs
doc.rb.erb,docs_kit.rb.erb,installation_page.rb.erb) rewritten to the v2pageDSL +nav_registries+ compact class, so install output matches generator output.Doc+ initializer converted to v2. Three titles that don't derive cleanly (Authoring pages→authoring/Authoring,Styling & CSS→styling/Styling,Code languages→languages/Languages) keep explicitslug:/view:overrides so URLs and view classes are preserved. Sidebar is byte-identical before/after.nav_registries(the custom lambda demoted to an "advanced" subsection); a new "Add a page" section leads with the generator and reframes hand-authoring as "under the hood". The dogfood authoring page does the same.Test plan
spec/docs_kit/registry_spec.rb— page derivation + overrides;all/groupedover page entries;view_classresolution underview_namespace;href;icon;nav_items(authored-only, hrefs/icons); view_namespace-unset → all unauthored; mixed-mode raises.spec/docs_kit/configuration_spec.rb—nav_registriesdefault/override;nav_groupsderivation; empty-group drop; explicit-nav-wins; empty fallback.spec/generators/page_generator_spec.rb— compact class + correct constants; v2 injection + ordering;--slug/--view/--eyebrow/--registry; legacy no-mutation; idempotent re-run + no file clobber.Verification
bundle exec rake— rspec 153 examples, 0 failures + rubocop cleanrails g docs_kit:page "Smoke Test" --group=Guide→ page renders at/docs/smoke-test, appears in sidebar (verified end-to-end over HTTP); reverted.entriesAPI and explicitc.navlambda both still work.